package com.bj58.ecdata.dao.basedao;

import java.sql.Connection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bj58.ecdata.dao.util.PropertiesHelper;
import com.bj58.ecdata.dbconnectionpool.ConnectionPool;
import com.bj58.ecdata.dbconnectionpool.ConnectionPoolFactory;
import com.bj58.ecdata.dbconnectionpool.DBConfig;

public class ConnectionHelper
{
  private ConnectionPool connPool;
  private final ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
  private static final Logger logger = LoggerFactory.getLogger(ConnectionHelper.class);
  
  public ConnectionHelper(String configPath)
    throws Exception
  {
    logger.info("creating DAOHelper configPath:" + configPath);
    PropertiesHelper ph = new PropertiesHelper(configPath);
    logger.info("init ConnectionPool...");
    
    String swapDataSource = ph.getString("swapDataSource");
    if (swapDataSource != null)
    {
      this.connPool = getDataSource(ph, swapDataSource);
      if (this.connPool == null) {
        throw new Exception("conn pool is null: " + configPath);
      }
    }
    else
    {
      this.connPool = createConnPool(ph);
    }
    logger.info("init ConnectionPool success connection count:" + this.connPool.GetAllCount());
    if (this.connPool.GetAllCount() == 0) {
      logger.warn("success create 0 connection, please check config!!!");
    }
  }
  
  private ConnectionPool getDataSource(PropertiesHelper ph, String swapDataSource)
    throws Exception
  {
    return ConnectionPoolFactory.createPool(ph,swapDataSource);
  }
  
  public Connection get()
    throws Exception
  {
    Connection conn = (Connection)this.threadLocal.get();
    if (conn == null) {
      conn = this.connPool.Get();
    }
    return conn;
  }
  
  public Connection getReadConnection()
    throws Exception
  {
    Connection conn = (Connection)this.threadLocal.get();
    if (conn == null) {
      conn = this.connPool.GetReadConnection();
    }
    return conn;
  }
  
  public void release(Connection conn)
  {
    Connection tconn = (Connection)this.threadLocal.get();
    if ((tconn == null) || (
      (tconn != null) && (tconn.hashCode() != conn.hashCode())))
    {
      logger.debug("this conn is release " + conn);
      this.connPool.Release(conn);
    }
  }
  
  public void lockConn(Connection conn)
  {
    this.threadLocal.set(conn);
  }
  
  public void unLockConn()
  {
    this.threadLocal.set(null);
  }
  
  public ConnectionPool getConnPool()
  {
    return this.connPool;
  }
  
  private ConnectionPool createConnPool(PropertiesHelper ph)
    throws Exception
  {
    logger.debug("ConnectionPool ConnetionURL:" + ph.getString("ConnetionURL"));
    logger.debug("ConnectionPool DriversClass:" + ph.getString("DriversClass"));
    logger.debug("ConnectionPool UserName:***");
    logger.debug("ConnectionPool PassWord:***");
    logger.debug("ConnectionPool MinPoolSize:" + ph.getInt("MinPoolSize"));
    logger.debug("ConnectionPool MaxPoolSize:" + ph.getInt("MaxPoolSize"));
    logger.debug("ConnectionPool IdleTimeout:" + ph.getInt("IdleTimeout"));
    logger.debug("ConnectionPool AutoShrink:" + ph.getBoolean("AutoShrink"));
    
    DBConfig config = new DBConfig();
    config.setConnetionUrl(ph.getString("ConnetionURL"));
    config.setDriversClass(ph.getString("DriversClass"));
    config.setUserName(ph.getString("UserName"));
    config.setPassWord(ph.getString("PassWord"));
    config.setMinPoolSize(ph.getInt("MinPoolSize"));
    config.setMaxPoolSize(ph.getInt("MaxPoolSize"));
    config.setIdleTimeout(ph.getInt("IdleTimeout"));
    config.setAutoShrink(Boolean.valueOf(ph.getBoolean("AutoShrink")));
    return new ConnectionPool(config);
  }
}
